using System;
using System.Net;

namespace gtalk
{
    /// <summary>
    /// Summary description for Jabber.
    /// </summary>
    public class Jabber
    {
        private string serverAddr = "";
        private int serverPort = -1;
        private string email = "";
        private string password = "";

        private agsXMPP.XmppClientConnection xmppClientConn;
        private Users.UserCollection userCollection;

        public string ServerAddr
        {
            get { return this.serverAddr; }
            set { this.serverAddr = value; }
        }

        public int ServerPort
        {
            get { return this.serverPort; }
            set { this.serverPort = value; }
        }

        public Jabber(string serverAddr, int serverPort, string email, string password)
        {
            this.serverAddr = serverAddr;
            this.serverPort = serverPort;
            this.email = email;
            this.password = password;

            this.XmppClientInitialize();
        }

        public Jabber()
        {
            this.serverAddr = Config.SocketServerAddr;
            this.serverPort = Config.SocketServerPort;
            this.email = Config.Email;
            this.password = Config.Password;

            this.XmppClientInitialize();
        }

        private void XmppClientInitialize()
        {
            this.userCollection = Users.UserCollection.Instance;

            this.xmppClientConn = new agsXMPP.XmppClientConnection();
            agsXMPP.Jid jid = new agsXMPP.Jid(this.email);

            this.xmppClientConn.Server = jid.Server;
            this.xmppClientConn.Port = this.serverPort;
            this.xmppClientConn.Username = jid.User;
            this.xmppClientConn.Password = this.password;
            this.xmppClientConn.Resource = "NuBackRommGroup";

            this.xmppClientConn.Priority = 10;
            this.xmppClientConn.UseSSL = false;
            this.xmppClientConn.AutoResolveConnectServer = true;

            this.xmppClientConn.ConnectServer = null;
            this.xmppClientConn.SocketConnectionType = agsXMPP.net.SocketConnectionType.Direct;

            this.xmppClientConn.UseStartTLS = true;

            this.xmppClientConn.OnReadXml += new agsXMPP.XmlHandler(xmppClientConn_OnReadXml);
            this.xmppClientConn.OnWriteXml += new agsXMPP.XmlHandler(xmppClientConn_OnWriteXml);
            this.xmppClientConn.OnRosterStart += new agsXMPP.ObjectHandler(xmppClientConn_OnRosterStart);
            this.xmppClientConn.OnRosterEnd += new agsXMPP.ObjectHandler(xmppClientConn_OnRosterEnd);
            this.xmppClientConn.OnRosterItem += new agsXMPP.XmppClientConnection.RosterHandler(xmppClientConn_OnRosterItem);
            this.xmppClientConn.OnLogin += new agsXMPP.ObjectHandler(xmppClientConn_OnLogin);
            this.xmppClientConn.OnClose += new agsXMPP.ObjectHandler(xmppClientConn_OnClose);
            this.xmppClientConn.OnError += new agsXMPP.ErrorHandler(xmppClientConn_OnError);
            this.xmppClientConn.OnPresence += new agsXMPP.XmppClientConnection.PresenceHandler(xmppClientConn_OnPresence);
            this.xmppClientConn.OnMessage += new agsXMPP.XmppClientConnection.MessageHandler(xmppClientConn_OnMessage);
            this.xmppClientConn.OnIq += new agsXMPP.Xml.StreamHandler(xmppClientConn_OnIq);

            this.xmppClientConn.ClientSocket.OnSend += new agsXMPP.net.BaseSocket.OnSocketDataHandler(ClientSocket_OnSend);
            this.xmppClientConn.ClientSocket.OnReceive += new agsXMPP.net.BaseSocket.OnSocketDataHandler(ClientSocket_OnReceive);
        }

        public void ConnectServer()
        {
            this.xmppClientConn.KeepAlive = true;
            this.xmppClientConn.Open();
        }

        public void BrodCast( string msgStr )
        {
            this.SendMsg(msgStr);
        }

        #region XmppClientConnEvents

        private void xmppClientConn_OnReadXml(object sender, string xml)
        {
            this.AddLog("Receive  \r\n" + xml);
        }

        private void xmppClientConn_OnWriteXml(object sender, string xml)
        {
            this.AddLog("Send  \r\n" + xml);
        }

        private void xmppClientConn_OnRosterStart(object sender)
        {

        }

        private void xmppClientConn_OnRosterEnd(object sender)
        {

        }

        private void xmppClientConn_OnRosterItem(object sender, agsXMPP.protocol.iq.roster.RosterItem item)
        {
            Console.WriteLine( "RosterItem : " + item.Name + " " + item.InnerXml );

            this.userCollection.SetUserRosterItem(item);
        }

        private void xmppClientConn_OnLogin(object sender)
        {
            this.xmppClientConn.Show = agsXMPP.protocol.client.ShowType.chat;
            this.xmppClientConn.SendMyPresence();
        }

        private void xmppClientConn_OnClose(object sender)
        {

        }

        private void xmppClientConn_OnError(object sender, Exception ex)
        {

        }

        private void xmppClientConn_OnPresence(object sender, agsXMPP.protocol.client.Presence pres)
        {

        }

        private void xmppClientConn_OnMessage(object sender, agsXMPP.protocol.client.Message msg)
        {
            this.Display("From " + msg.From + " : " + msg.Body );

            Users.User msgFromUser = this.userCollection.GetUserByName(msg.From.User);

            if (msg.Type != agsXMPP.protocol.client.MessageType.error)
            {
                if (msg.Body == "/userlist")
                {
                    this.SendMsg(msg.From, this.userCollection.ToString());
                }
                else if ( msg.Body.StartsWith( "/sign" ) )
                {
                    if (!object.Equals(msgFromUser, null))
                    {
                        string commonStr = msg.Body.Trim();
                        string[] commonStrs = msg.Body.Split(' ');
                        if (commonStrs.Length <= 1)//return the user sign
                        {
                            this.SendMsg(msg.From,
                                "Your sign : " + msgFromUser.Sign +
                                "\r\n \"/sign [new sign]\" : update your sign.");
                        }
                        else
                        {
                            Users.User tmpUser = this.userCollection.GetUserByName(msg.From.User);
                            tmpUser.Sign = commonStr.Substring(commonStr.IndexOf(' '));
                            this.SendMsg(msg.From,
                                string.Format("Your new sign : {0}", tmpUser.Sign));
                        }
                    }
                }
                else
                {
                    foreach (Users.User user in this.userCollection)
                    {
                        if (user.UserName != msg.From.User)
                            if (!object.Equals(user.RosterItem, null))
                            {
                                if (!object.Equals( msgFromUser, null ))
                                    this.SendMsg(user.RosterItem.Jid, msgFromUser.Sign + " : " + msg.Body);
                                else
                                    this.SendMsg(user.RosterItem.Jid, msg.From.User + " : " + msg.Body);
                            }
                    }
                }

                //switch (msg.Body.Split(' ')[0])
                //{
                //    case "/userlist":
                //        {
                //            //string userListStr = "";
                //            //foreach (agsXMPP.Jid jid in this.jidList)
                //            //    userListStr += jid.User + ";\r\n";
                //            //this.SendMsg(msg.From, userListStr);
                //            this.SendMsg(msg.From, this.userCollection.ToString());
                //        }
                //        break;
                //    default:
                //        foreach (Users.User user in this.userCollection)
                //        {
                //            if (user.UserName != msg.From.User)
                //                this.SendMsg(user.RosterItem.Jid, user.Sign + " : " + msg.Body);
                //        }
                //        break;
                //}
            }
        }

        private void xmppClientConn_OnIq(object sender, agsXMPP.Xml.Dom.Node e)
        {

        }

        private bool ClientSocket_OnValidateCertificate(System.Security.Cryptography.X509Certificates.X509Certificate certificate, int[] certificateErrors)
        {
            return false;
        }

        private void ClientSocket_OnSend(object sender, byte[] data, int count)
        {

        }

        private void ClientSocket_OnReceive(object sender, byte[] data, int count)
        {

        }

        #endregion XmppClientConnEvents

        private void SendMsg( string msgStr )
        {
            foreach (Users.User user in this.userCollection)
            {
                if( !object.Equals( user.RosterItem, null) )
                    this.SendMsg(user.RosterItem.Jid, "Broadcast : " + msgStr);
            }
        }

        private void SendMsg( agsXMPP.Jid jid, string msgStr )
        {
            agsXMPP.protocol.client.Message msg = new agsXMPP.protocol.client.Message();
            msg.Type = agsXMPP.protocol.client.MessageType.chat;
            msg.To = jid;
            msg.Body = msgStr;

            this.xmppClientConn.Send(msg);

            this.Display("send to " + jid.User + " : " + msgStr);
        }

        private void Display( string str )
        {
            Console.WriteLine(str);
        }

        private void AddLog(string logStr)
        {
            //Console.WriteLine(logStr);
        }
    }
}
